﻿using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.ComponentModel;
using System.Reflection;
using System.Text;

namespace TK.Common.Swagger
{
    /// <summary>
    /// EnumSchemeFilter
    /// </summary>
    public class EnumSchemeFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            var enumType = GetNullableEnum(context.Type);
            if (context.Type.IsEnum || enumType != null)
            {
                schema.Description = ToEnumDesc(enumType ?? context.Type);
                schema.Type = context.Type.IsEnum ? context.Type.Name : enumType.Name;
                schema.Format = schema.Type;
                EnumDescriptionList.Dic.TryAdd(schema.Type, schema.Description);
            }
        }

        #region private methods
        /// <summary>
        /// 获取可空类型枚举参数，无返回nu..
        /// </summary>
        private Type GetNullableEnum(Type type)
        {
            if (type.IsReferenceOrNullableType())
            {
                return type.GenericTypeArguments.FirstOrDefault(m => m.IsEnum);
            }

            return null;
        }

        /// <summary>
        /// 拼接信息
        /// </summary>
        private string ToEnumDesc(Type type)
        {
            var stringBuilder = new StringBuilder();
            Enum.GetNames(type)
                .ToList()
                .ForEach(name =>
                {
                    var e = (Enum)Enum.Parse(type, name);
                    var data = $"{Convert.ToInt64(Enum.Parse(type, name))} {ToDescription(e)}、";

                    stringBuilder.Append(data);
                });
            return stringBuilder.ToString().TrimEnd('、');
        }

        /// <summary>
        /// 获取枚举描述
        /// </summary>
        /// <param name="value">enum</param>
        /// <returns></returns>
        private string ToDescription(Enum value)
        {
            var type = value.GetType();
            var name = Enum.GetName(type, value);
            if (string.IsNullOrWhiteSpace(name))
            {
                return value.ToString();
            }

            var field = type.GetField(name);
            var description = field?.GetCustomAttribute<DescriptionAttribute>();
            return description == null ? value.ToString() : description.Description;
        }
        #endregion
    }

    /// <summary>
    /// swagger 枚举数据存储类
    /// </summary>
    public class EnumDescriptionList
    {
        /// <summary>
        /// 枚举描述字典：key->枚举名称；value:所有枚举值及对应描述
        /// </summary>
        public static Dictionary<string, string> Dic = new Dictionary<string, string>();
    }
}
